import logging

from fastapi import APIRouter, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer

from app.schemas.token import Token, APIResponse, LoginRequest
from app.admin.schemas.user import User, ChangePassword
from app.security.auth import get_current_active_user
from app.security.auth_service import auth_service
from app.admin.services.user_service import user_service
from app.core.config import settings
from pydantic import BaseModel

router = APIRouter()

# 配置日志
logger = logging.getLogger(__name__)


oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/v1/auth/login")

@router.post("/login", response_model=APIResponse[Token])
async def login_for_access_token(
        request: LoginRequest
):
    """
    用户登录并获取访问令牌
    """
    logger.debug(f"租户 [{request.tenant_id}] ，用户 [{request.login_name}] 尝试登录...")
    user = await auth_service.authenticate_user(request.login_name, request.password, request.tenant_id)
    if not user:
        logger.warning(f"租户 [{request.tenant_id}] ，用户 [{request.login_name}] 登录失败: 用户名、密码或租户ID错误")
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="用户名、密码或租户ID不正确！",
            headers={"WWW-Authenticate": "Bearer"},
        )
    
    access_token = auth_service.create_access_token(user.login_name, user.full_name, user.tenant_id)
    refresh_token = auth_service.create_refresh_token(user.login_name, user.full_name, user.tenant_id)
    
    logger.info(f"租户 [{request.tenant_id}] ，用户 [{request.login_name}] 登录成功。")
    return APIResponse(
        code=200,
        msg="登录成功",
        data=Token(
            access_token=access_token, 
            token_type="bearer",
            refresh_token=refresh_token,
            expires_in=settings.ACCESS_TOKEN_EXPIRE_MINUTES * 60
        )
    )


@router.post("/logout", response_model=APIResponse[dict])
async def logout(
        current_user: User = Depends(get_current_active_user)
):
    """
    用户登出
    """
    logger.info(f"用户 [{current_user.login_name}] 登出成功。")
    # 在服务器端，JWT是无状态的，不需要特殊处理
    # 但我们可以记录登出事件，并在客户端删除token
    return APIResponse(
        code=200,
        msg="登出成功",
        data={}
    )


@router.get("/me", response_model=APIResponse[User])
async def read_users_me(
        current_user: User = Depends(get_current_active_user)
):
    """
    获取当前用户信息
    """
    logger.debug(f"当前用户详细信息: {current_user}")
    return APIResponse(
        code=200,
        msg="获取用户信息成功",
        data=current_user
    )


class RefreshTokenRequest(BaseModel):
    refresh_token: str


@router.post("/refresh-token", response_model=APIResponse[Token])
async def refresh_access_token(
        request: RefreshTokenRequest
):
    """
    使用刷新令牌获取新的访问令牌
    """
    logger.debug(f"尝试使用刷新令牌获取新的访问令牌")
    
    token_data = auth_service.verify_refresh_token(request.refresh_token)
    if not token_data:
        logger.warning("刷新令牌无效或已过期")
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="刷新令牌无效或已过期",
            headers={"WWW-Authenticate": "Bearer"},
        )
    # 创建新的访问令牌和刷新令牌
    access_token = auth_service.create_access_token(token_data.login_name, token_data.full_name, token_data.tenant_id)
    refresh_token = auth_service.create_refresh_token(token_data.login_name, token_data.full_name, token_data.tenant_id)
    
    logger.info(f"用户 [{token_data.login_name}] 刷新令牌成功")
    return APIResponse(
        code=200,
        msg="令牌刷新成功",
        data=Token(
            access_token=access_token, 
            token_type="bearer",
            refresh_token=refresh_token,
            expires_in=settings.ACCESS_TOKEN_EXPIRE_MINUTES * 60
        )
    )


@router.post("/change-password", response_model=APIResponse[dict])
async def change_password(
        request: ChangePassword,
        current_user: User = Depends(get_current_active_user)
):
    """
    用户修改密码（需要验证旧密码）
    """
    logger.info(f"用户尝试修改密码: {current_user.login_name}")
    
    success = await user_service.change_password(
        current_user.id, 
        request.old_password, 
        request.new_password
    )
    
    if success:
        logger.info(f"密码修改成功: {current_user.login_name}")
        return APIResponse(
            code=200,
            msg="密码修改成功",
            data={}
        )
    else:
        logger.warning(f"密码修改失败: {current_user.login_name}")
        return APIResponse(
            code=400,
            msg="密码修改失败，旧密码错误",
            data={}
        )